package com.yu.thread7;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * Created by yuxiaolong on 2015/4/2.
 * 生产者消费者
 */
public class Restaurant {

    Meal meal;
    WaitPersion waitPersion = new WaitPersion(this);
    Chef chef = new Chef(this);
    ExecutorService exec = Executors.newCachedThreadPool();

    public Restaurant(){
        exec.execute(waitPersion);
        exec.execute(chef);
    }

    public static void main(String[] args) {
        new Restaurant();
    }

}

class Meal{
    private final int orderNum;

    public Meal(int orderNum){
        this.orderNum = orderNum;
    }

    @Override
    public String toString() {
        return "Meal:" + orderNum;
    }
}

class WaitPersion implements Runnable{

    private Restaurant restaurant;

    public WaitPersion(Restaurant restaurant){
        this.restaurant = restaurant;
    }

    @Override
    public void run() {
        while(true){ //while(!Thread.interrupted())  //如果替换成死循环则会在下次循环后一直在这里等待，中断wait只有一次
            try {
                synchronized (this) {
                    while (restaurant.meal == null) {
                        wait();
                    }
                }

                System.out.println("WaitPersion got " + restaurant.meal);
                synchronized (restaurant.chef) {
                    System.out.println("synchronize chef");
                    restaurant.meal = null;
                    restaurant.chef.notifyAll();
                }
                System.out.println("out synchronize chef");
            } catch (InterruptedException e){
                System.out.println("WaitPersopm interrupted");
            }
        }

    }
}
class Chef implements Runnable{
    private Restaurant restaurant;
    public Chef(Restaurant restaurant){
        this.restaurant = restaurant;
    }
    private int count = 0;
    @Override
    public void run() {
        try {
            while (!Thread.interrupted()) {
                synchronized (this) {
                    while (restaurant.meal != null) {
                        wait();
                    }
                }

                if(++count == 10){
                    System.out.println("Out of food, closing");
                    restaurant.exec.shutdownNow();
                }

                System.out.println("Order up!");
                synchronized (restaurant.waitPersion){
                    System.out.println("synchronized waitPersion");
                    restaurant.meal = new Meal(count);
                    restaurant.waitPersion.notifyAll();
                }
                System.out.println("before sleep");
                TimeUnit.MILLISECONDS.sleep(100);
            }
        }catch (InterruptedException e){
            System.out.println("Chef interruption");
        }
    }
}
